package batch.process.cdi;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

import net.ftp.client.GenericFtpClient;
import net.ftp.client.core.FtpClient;
import batch.process.cdi.bean.CDIBean;
import batch.process.external.BatchProcessExternalAppFacade;
import batch.process.external.app.ftpserver.BatchProcessFtpClientApp;
import batch.process.utils.BatchProcessLogger;
import batch.process.utils.BatchProcessProperties;
import batch.process.utils.BatchProcessUtils;
import batch.process.utils.Constant;

public class CDIRetriever implements Serializable {

	private static final long serialVersionUID = 1L;

	private BatchProcessFtpClientApp ftpClient = null;	
	private static BatchProcessLogger logger = null;

	private String hostName = null;
	private String wrkDir = null;
	private int hostPort = -1;
	private String userName = null;
	private String password = null;
	private boolean proxyServer = false;	
	private boolean printCommandOutput = false;
	
	private String lastUpdateFilePath = null;
	private String lastUpdateFileName = null;
	
	private void init() throws Exception {
		this.initFtpClientInfo();
		this.initCDIRetrieverInfo();
	}

	private void initFtpClientInfo() throws Exception{
		try {
			
			logger.info(" Reading key [FTP_SERVER_NAME] ...", CDIRetriever.class);
			hostName = BatchProcessProperties.getProperty("FTP_SERVER_NAME");
			
			logger.info(" Reading key [FTP_SERVER_WRK_DIR] ...", CDIRetriever.class);
			wrkDir = BatchProcessProperties.getProperty("FTP_SERVER_WRK_DIR");
			
			logger.info(" Reading key [FTP_SERVER_PORT] ...", CDIRetriever.class);
			hostPort = BatchProcessProperties.getInteger("FTP_SERVER_PORT",
					GenericFtpClient.DEFAULT_FTP_PORT);
			
			logger.info(" Reading key [FTP_USER_NAME] ...", CDIRetriever.class);
			userName = BatchProcessProperties.getProperty("FTP_USER_NAME");
			
			logger.info(" Reading key [FTP_PASSWORD] ...", CDIRetriever.class);
			password = BatchProcessProperties.getProperty("FTP_PASSWORD");	
			
			logger.info(" Reading key [FTP_PROXY_SERVER] ...", CDIRetriever.class);
			proxyServer = BatchProcessProperties.getBoolean("FTP_PROXY_SERVER");			
			
			logger.info(" Reading key [FTP_DEBUG_MODE] ...", CDIRetriever.class);
			printCommandOutput = BatchProcessProperties.getBoolean("FTP_DEBUG_MODE");
			
		} catch (Exception e) {
			logger.error(" Error initiating Ftp Server Info ..." + e, CDIRetriever.class);
			throw(e);
		}
	}
	
	private void initCDIRetrieverInfo() throws Exception{
		try {
			
			logger.info(" Reading key [LAST_UPDATE_FILE_PATH] ...", CDIRetriever.class);
			lastUpdateFilePath = BatchProcessProperties.getProperty("LAST_UPDATE_FILE_PATH");

			logger.info(" Reading key [LAST_UPDATE_FILE_NAME] ...", CDIRetriever.class);
			lastUpdateFileName = BatchProcessProperties.getProperty("LAST_UPDATE_FILE_NAME");

		} catch (Exception e) {
			logger.error(" Error initiating CDI Retriever Info ..." + e, CDIRetriever.class);
			throw(e);
		}
	}

	
	public CDIRetriever() throws Exception {		
		try {
			logger = new BatchProcessLogger();
			init();			
			ftpClient = BatchProcessExternalAppFacade.getFtpClientInterface();
			ftpClient.setup(hostName, hostPort, userName,
					password, proxyServer, printCommandOutput);
			this.connect();
		} catch (Exception e) {
			logger.error(" Error on CDI Retriever ..." + e, CDIRetriever.class);
			e.printStackTrace();
			throw(e);
		}		
		
	}
	
	public void connect() throws SocketException, IOException {		
		ftpClient.connect();		
	}

	
	public void disconnect() {
		if (ftpClient.isConnected()) {  
			try {
				ftpClient.disconnect();
			} catch (Exception e) {
				logger.error(" Error disconnecting from ftp server ..." + e, CDIRetriever.class);
				e.printStackTrace();
			}
		}
	}

	public boolean login() {
		boolean result = false;
		try {
			result = ftpClient.login();
		} catch (Exception e) {
			result = false;
			logger.error(" Error logging out from ftp server ..." + e, CDIRetriever.class);
			e.printStackTrace();
		}
		return(result);
	}

	public boolean logout() {
		boolean result = false;
		try {
			if (ftpClient.isConnected()) {  
				result = ftpClient.logout();
			}
		} catch (IOException e) {
			result = false;
			logger.error(" Error logging out from ftp server ..." + e, CDIRetriever.class);
			e.printStackTrace();
		} catch (Exception e) {
			result = false;
			logger.error(" Error logging out from ftp server ..." + e, CDIRetriever.class);
			e.printStackTrace();
		}
		return(result);
	}


	@SuppressWarnings("deprecation")
	public Collection<CDIBean> retrieveCDI(Date date) {
		ArrayList<CDIBean> cdiBeanList = null;
		File file = null;
		Date actualDate = null;
		Date lastUpdate = null;
		String serverFileName = null;
		CDIBean cdiBean = null;
		
		try {
			
			if (ftpClient.isConnected()) {			
				if (this.login()) {
					ftpClient.changeWorkingDirectory(wrkDir);
							
					actualDate = new Date(date.getTime());
					
					lastUpdate = BatchProcessUtils.getLastUpdateFile(lastUpdateFilePath,lastUpdateFileName);
					BatchProcessUtils.createTempDir(Constant.MAIN_TEMP_DIR_PATH);				
					
					while (BatchProcessUtils.dateCompare(
							lastUpdate, actualDate, 
								new SimpleDateFormat(Constant.ftpFileDateFormatStr)) <= 0){
						
						if (!BatchProcessUtils.isWeekend(lastUpdate)) {
						
							serverFileName = BatchProcessUtils.dateConvert(
									new SimpleDateFormat(
											Constant.ftpFileDateFormatStr), lastUpdate) + ".txt";
													
							file = ftpClient.retrieveFile(serverFileName, 
									FtpClient.ASCII_FILE_TYPE, Constant.MAIN_TEMP_DIR_PATH + serverFileName);
							
							if (file != null) {							
								cdiBean = this.populateCDIBean(file,serverFileName);								
								if (cdiBean != null) {
									if (cdiBeanList == null) {
										cdiBeanList = new ArrayList<CDIBean>();	
									}									
									cdiBeanList.add(cdiBean);								
								}								
								file.delete();
							} else {
								logger.info(" The file " + serverFileName + " was not found on the ftp server ", CDIRetriever.class);
							}
						}
						
						lastUpdate.setDate(lastUpdate.getDate() + 1);
					}
					
					BatchProcessUtils.setLastUpdateFile(lastUpdateFilePath, lastUpdateFileName,	new Date());
				}
			}
			
		} catch (Exception e) {
			logger.error(" Error retrieving CDI files ..." + e, CDIRetriever.class);
			e.printStackTrace();
		} finally {			
			this.logout();			
			this.disconnect();			
		}
		
		return(cdiBeanList);
	}
	
	private CDIBean populateCDIBean(File file, String fileName) {
		CDIBean cdiBean = null;
		BufferedReader in = null;
		
		try {
		
			in = new BufferedReader(new FileReader(file));
        	BigDecimal cdiValue = new BigDecimal(
        			in.readLine().trim()).divide(new BigDecimal(100));
	        cdiBean = this.populateCDIBean(
	        		BatchProcessUtils.dateConvert(
	        				new SimpleDateFormat(Constant.ftpFileDateFormatStr),
	        				fileName.substring(0, fileName.indexOf(".txt"))), 
	        							cdiValue);
		} catch (NumberFormatException e) {
			logger.error(" Error populating CDI bean ..." + e, CDIRetriever.class);
			e.printStackTrace();
			cdiBean = null;
		} catch (Exception e) {
			logger.error(" Error populating CDI bean ..." + e, CDIRetriever.class);
			e.printStackTrace();
			cdiBean = null;
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				logger.error(" Error populating CDI bean ..." + e, CDIRetriever.class);
				e.printStackTrace();
				cdiBean = null;
			}
		}
		return(cdiBean);
   }
	
	private CDIBean populateCDIBean(Date date, BigDecimal value) {
		return(new CDIBean(date,value));
   }

	
}
